//
//  InstallLayer.cpp
//  client
//
//  Created by sg on 2/17/17.
//
//

#include "InstallLayer.h"

#include "ui/CocosGUI.h"
#include "AppDelegate.h"
#include "CCLuaEngine.h"
#include "MessageDialog.h"
#include "ConfirmBox.h"
#include "UserDefaultKeys.h"
#include "NodePool.hpp"
#include "CCFactory.h"
#include "custom/Utils.h"
#include "AudioEngine.h"
#include "Localization.h"
#include "TableCache.h"

#if CC_TARGET_PLATFORM==CC_PLATFORM_ANDROID
#include "jni/Java_org_cocos2dx_lib_Cocos2dxHelper.h"
#endif

USING_NS_CC;
using namespace cocos2d::ui;
using namespace dragonBones;

#if (CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID || CC_TARGET_PLATFORM == CC_PLATFORM_IOS)
using namespace cocos2d::experimental::ui;
#endif

#define LOGIN_CSB "ui2/login/Login_start.csb"
#define LOGIN_EFC_PATH "armatures/effect/login/"

static std::string s_EmaQA_str = "Wjyz2DTest";
static std::string s_TXQA_str = "Wjyz2DTencentTest";
static std::string s_TXPre_str = "Wjyz2DTencentPre";

InstallLayer::InstallLayer():
_progressLabel(nullptr)
,_assetIdLabel(nullptr)
,_loadingBarTotal(nullptr)
,_loadingBarFile(nullptr)
,_loadingBarLight(nullptr)
,_blackLayer(nullptr)
,_updateSuccess(false)
{
    
}

InstallLayer::~InstallLayer()
{
   
}

void InstallLayer::onKeyPressed(EventKeyboard::KeyCode keyCode, Event* event)
{
    Layer::onKeyPressed(keyCode, event);
    
    if (keyCode == EventKeyboard::KeyCode::KEY_BACK)
    {
        cocos2d::log("===>InstallLayer   menuCloseCallback ");
        AppDelegate::closeApp();
    }
}

// on "init" you need to initialize your instance
bool InstallLayer::init()
{
    if (!Layer::init())
    {
        return false;
    }
    cocos2d::log("===>InstallLayer   init ");
    Size visibleSize = Director::getInstance()->getVisibleSize();
    Vec2 origin = Director::getInstance()->getVisibleOrigin();

    // notice 热更新界面所需资源，必须保证新／旧程序能够兼容（ui可访问结构不变，资源目录名字不变）
    // 这样才能更新程序时不报错，并且可以更新热更新界面本身
    
    // add "Logo" splash screen"
    CSLoader::getInstance()->setAutoPlayAni(true);
    CSLoader::getInstance()->setBindingDelegate([this](const std::string& classname,const std::string& name,Node* node){
        if(name=="_loadingBarTotal")
        {
            _loadingBarTotal = dynamic_cast<ui::LoadingBar*>(node);
        }
        else if(name=="_loadingBarFile")
        {
            _loadingBarFile = dynamic_cast<ui::LoadingBar*>(node);
        }
        else if(name=="_progressLabel")
        {
            _progressLabel = dynamic_cast<ui::Text*>(node);
        }
        else if(name=="_assetIdLabel")
        {
            _assetIdLabel = dynamic_cast<ui::Text*>(node);
        }
        else if(name=="_loadingBarLight")
        {
            _loadingBarLight = node;
        }
    });
    Node* hotfix=CSLoader::createNode(LOGIN_CSB);
    hotfix->setName("hotfix");
    hotfix->setContentSize(Size(visibleSize.width,visibleSize.height));
    
    // add bg armature
    auto fileUtils = FileUtils::getInstance();
    Node* bgPanel = hotfix->getChildByName("bg");

    //腾讯显示批文
    std::string publisher = Configuration::getInstance()->getValue("Publisher", Value("develop")).asString();
    if(publisher == "tencent")
    {
        Node* text = bgPanel->getChildByName("Text");
        Node* text_1 = bgPanel->getChildByName("Text_1");
        if(text != nullptr)
        {
            text->setVisible(true);
        }
        if(text_1 != nullptr)
        {
            text_1->setVisible(true);
        }
    }

    // 加载背景动画
    Node* aniPanel = bgPanel->getChildByName("Panel_ani");
    if(aniPanel != nullptr)
    {
        auto factory = dragonBones::CCFactory::getInstance();
        std::string skeletonPath;
        std::string texturePath;
        std::string skeletonKey;
        std::string textureKey;
        
        std::string skeletonDir = LOGIN_EFC_PATH;
        if(fileUtils->isFileExist(skeletonDir + "skeleton.bin"))
        {
            skeletonPath = skeletonDir + "skeleton.bin";
            texturePath = skeletonDir + "texture.bin";
            skeletonKey = fileUtils->fullPathForFilename(skeletonPath);
            textureKey = fileUtils->fullPathForFilename(texturePath);
        }
        else
        {
            skeletonPath = skeletonDir + "skeleton.xml";
            texturePath = skeletonDir + "texture.xml";
            skeletonKey = fileUtils->fullPathForFilename(skeletonPath);
            textureKey = fileUtils->fullPathForFilename(texturePath);
        }
        
        factory->loadDragonBonesData(skeletonPath, skeletonKey);
        factory->loadTextureAtlasData(texturePath, textureKey, 0, false);
        auto armature = factory->buildArmatureDisplay("login", skeletonKey, textureKey);
        auto animation = armature->getAnimation();
        animation->play("login", 0);

        aniPanel->addChild(armature);
    }
    
    _loadingPanel = hotfix->getChildByName("Panel");
    setLoadingVisible(false);

    //SpriteFrameCache::getInstance()->retainSpriteFramesFromFile("ui/ui_resources/commonUI.plist");
    SpriteFrameCache::getInstance()->retainSpriteFramesFromFile("ui2/ui_resources/common.plist");
    
    this->addChild(hotfix);
    cocos2d::ui::Helper::doLayout(hotfix);

    if(_loadingBarFile)
    {
        _loadingBarFile->setPercent(0);
        _loadingBarFile->getParent()->setVisible(false);
    }
    
    updateStageLabel("");
    updateProgressLabel("");
    updateProgressBar(0);

    return true;
}

void InstallLayer::setLoadingVisible(bool isVisible)
{
    if(_loadingPanel)
    {
         _loadingPanel->setVisible(isVisible);
    }
}

void InstallLayer::onEnterTransitionDidFinish()
{
    Layer::onEnterTransitionDidFinish();
    cocos2d::log("===>InstallLayer   onEnterTransitionDidFinish ");
    scheduleUpdate();
    _requestReviewState();
}

void InstallLayer::onExit()
{
    Layer::onExit();
    NodePool::getInstance()->clear();
    goExit();
}

void InstallLayer::goStart()
{
    _updateSuccess = true;
}

void InstallLayer::goExit()
{
    
}

void InstallLayer::goNext()
{
    runMainLua();
}

void InstallLayer::update(float dt)
{
    if(_updateSuccess)
    {
        _updateSuccess = false;
        goNext();
    }
}

void InstallLayer::runMainLua()
{
//    Director::getInstance()->getScheduler()->performFunctionInCocosThread([](){
        auto engine = LuaEngine::getInstance();
        engine->getLuaStack()->clean();
        std::string enterFile = Configuration::getInstance()->getValue("EntryScript",Value("main.lua")).asString();
        // Consider search path.
        enterFile = FileUtils::getInstance()->fullPathForFilename(enterFile);
        engine->executeScriptFile(enterFile.c_str());
//    });
}

void InstallLayer::updateProgressBar(int p)
{
    if(_loadingBarTotal)
    {
        _loadingBarTotal->setPercent(p);
    }

    if(_loadingBarLight && _loadingBarTotal)
    {
        float width = _loadingBarTotal->getContentSize().width;
        Vec2 barPos = _loadingBarTotal->getAnchorPointInPoints();
        Vec2 barLeftPos = Vec2(barPos.x-width*0.5,barPos.y);
        Vec2 pos = Vec2(barLeftPos.x+width*(p*0.01),barLeftPos.y);
        Vec2 wp = _loadingBarTotal->convertToWorldSpace(pos);
        Vec2 lp = _loadingBarLight->getParent()->convertToNodeSpace(wp);
        _loadingBarLight->setPosition(lp);
        _loadingBarLight->setVisible(p>0);
    }
}

void InstallLayer::updateStageLabel(const std::string& s)
{
    if(_assetIdLabel){
        _assetIdLabel->setString(s);
        _assetIdLabel->setVisible(!s.empty());
    }
}

void InstallLayer::updateProgressLabel(const std::string& s)
{
    if(_progressLabel){
        _progressLabel->setString(s);
        _progressLabel->setVisible(!s.empty());
    }
}

void InstallLayer::_requestReviewState()
{
#ifdef CHECK_REVIEW
    Configuration* configuration = Configuration::getInstance();
    configuration->setValue(UD_IS_APPLE_REVIEW, Value(false));
    configuration->setValue(UD_GATE_HOST_REDIRECT_URL, Value(""));

    // 测试使用，根据手机别名进入不同的测试环境
    std::string phoneName = Application::getInstance()->getPhoneName();
    std::string gateHost = "";
    if (Utils::checkStringIsEndWith(phoneName, s_TXPre_str))
    {
        gateHost = configuration->getValue("TXPreGateHostsQQ", Value("")).asString();
    }
    else if(Utils::checkStringIsEndWith(phoneName, s_TXQA_str))
    {
        gateHost = configuration->getValue("TXQAGateHostsQQ", Value("")).asString();
    }
    else if(Utils::checkStringIsEndWith(phoneName, s_EmaQA_str))
    {
        gateHost = configuration->getValue("EmaQAGateHostsQQ", Value("")).asString();
    }

    if (gateHost.empty())
    {
        gateHost = configuration->getValue("GateHostsQQ", Value("")).asString();
    }
    
    if (gateHost.empty())
    {
        gateHost = configuration->getValue("GateHosts", Value("")).asString();
    }
    
    if(gateHost != "")
    {
        char lastChar = gateHost[gateHost.size() -1];
        if(lastChar != '/')
        {
            gateHost = gateHost + "/";
        }
        std::string appVersion = Application::getInstance()->getAppVersion();
        std::string srcVersion = Application::getInstance()->getResourceVersion();
        
        std::string version = appVersion + "." + srcVersion;
        
        ApplicationProtocol::Platform platform = Application::getInstance()->getTargetPlatform();
        std::string strPlatform = "";
        switch (platform)
        {
            case ApplicationProtocol::Platform::OS_ANDROID:
                strPlatform = "android";
                break;
            case ApplicationProtocol::Platform::OS_IPHONE:
            case ApplicationProtocol::Platform::OS_IPAD:
                strPlatform = "ios";
                break;
            case ApplicationProtocol::Platform::OS_MAC:
                strPlatform = "mac";
                break;
            case ApplicationProtocol::Platform::OS_WINDOWS:
                strPlatform = "windows";
                break;
            default:
                break;
        }
        std::string url = gateHost + "appleversion?os="+strPlatform+"&version="+version;
        
        network::HttpRequest* request = new (std::nothrow) network::HttpRequest();
        request->setUrl(url);
        request->setRequestType(network::HttpRequest::Type::GET);
        request->setResponseCallback(this, httpresponse_selector(InstallLayer::_onReviewStateResponded));
        network::HttpClient::getInstance()->sendImmediate(request);
        request->release();
    }
    else
    {
        _beforeGoStart();
    }
#else
    _beforeGoStart();
#endif
}

void InstallLayer::_onReviewStateResponded(network::HttpClient *sender, network::HttpResponse *response)
{
    if (!response->isSucceed())
    {
        _beforeGoStart();
        return ;
    }

    std::vector<char> *buffer = response->getResponseData();
    if(buffer == nullptr)
    {
        _beforeGoStart();
        return ;
    }
    
    std::string bufffff(buffer->begin(), buffer->end());
    rapidjson::Document doc;
    if (doc.Parse<0>(bufffff.c_str()).HasParseError())
    {
        _beforeGoStart();
        return;
    }
    if (doc.HasMember("ret"))
    {
        const rapidjson::Value& retJson = doc["ret"];
        int ret = retJson.GetInt();
        if(ret == 0)
        {
            if (doc.HasMember("data"))
            {
                const rapidjson::Value& dataJson = doc["data"];
                if(dataJson.IsObject())
                {
                    if (dataJson.HasMember("redirecturl"))
                    {
                        const rapidjson::Value& redirecturlJson = dataJson["redirecturl"];
                        std::string redirecturlStr = redirecturlJson.GetString();
                        if (redirecturlStr != "")
                        {
                            Configuration* configuration = Configuration::getInstance();
                            CCLOG("set redirecturl %s , isReview = true", redirecturlStr.c_str());
                            configuration->setValue(UD_IS_APPLE_REVIEW, Value(true));
                            configuration->setValue(UD_GATE_HOST_REDIRECT_URL, Value(redirecturlStr));
                        }
                    }
                }
            }
        }
    }
    _beforeGoStart();
}

void InstallLayer::_updateLoadingBarVisible()
{
#ifdef CHECK_REVIEW
    Configuration* configuration = Configuration::getInstance();

    bool isReview = false;
    const Value& isReviewValue = configuration->getValue(UD_IS_APPLE_REVIEW);
    if(!isReviewValue.isNull()){
        isReview = isReviewValue.asBool();
    }
    setLoadingVisible(!isReview);
#else
    setLoadingVisible(true);
#endif
}

void InstallLayer::_beforeGoStart()
{
    Configuration* configuration = Configuration::getInstance();
#ifdef USE_GCLOUD
    if (configuration)
    {
        std::string permissions = configuration->getValue(UD_ANDROID_PERMISSIONS, Value("")).asString();
        AppDelegate::requestPermissions(permissions.c_str());
    }
#endif

#if (CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID || CC_TARGET_PLATFORM == CC_PLATFORM_IOS)
    bool isReview = false;
    const Value& isReviewValue = configuration->getValue(UD_IS_APPLE_REVIEW);
    if(!isReviewValue.isNull())
    {
        isReview = isReviewValue.asBool();
    }
    
    #if CC_TARGET_PLATFORM == CC_PLATFORM_IOS
    //检测iOS设备内存是否达标
    if(!isReview)
    {
        float totalMemoryGB = Utils::getTotalMemoryGB();
        cocos2d::log("InstallLayer _beforeGoStart iOS memory:%f \n", totalMemoryGB);
        float memoryLimit = configuration->getValue(MEMORY_LIMIT_GB, Value(1.5f)).asFloat();
        if (totalMemoryGB < memoryLimit)
        {
            MessageDialog* dialog = MessageDialog::create();
            dialog->setConfirmButton(Localization::getInstance()->getStr("CommonBtnConfirm").c_str());
            dialog->setConfirmCallback([](MessageDialog* sender){
                sender->removeFromParent();
                Director::getInstance()->end();
                exit(0);
            });
            dialog->setMessage(Localization::getInstance()->getStr("hotfix_error_device_not_supported").c_str());
            this->addChild(dialog);
            return;
        }
    }
    #endif
    bool isNeedFirstExtract = false;
    #ifdef USE_GCLOUD
        //dophin
        auto userDefault = UserDefault::getInstance();
        if(userDefault->getIntegerForKey(UD_FIRST_EXTRACT,-1) <= 0)
        {
            isNeedFirstExtract = true;
        }
    #endif
    //提审时需要在首包解压时播放一个视频，免得首包解压时间过长导致不过审
    if(isReview && isNeedFirstExtract)
    {
        Size visibleSize = Director::getInstance()->getVisibleSize();
        Vec2 origin = Director::getInstance()->getVisibleOrigin();
        
        // play logo video if file exist
        FileUtils* fileUtils = FileUtils::getInstance();
        std::string path = fileUtils->fullPathForFilename("res/video/TSLoading.mp4");
        bool isExist = fileUtils->isFileExist(path);
        if (isExist)
        {
            if(_blackLayer == nullptr)
            {
                _blackLayer = ui::Layout::create();
                _blackLayer->setContentSize(Director::getInstance()->getWinSizeInPixels());
                _blackLayer->setBackGroundColor(Color3B::BLACK);
                _blackLayer->setBackGroundColorType(ui::Layout::BackGroundColorType::SOLID);
                this->addChild(_blackLayer);
            }
            _blackLayer->setVisible(true);
            
            cocos2d::log("InstallLayer::_beforeGoStart VideoPlayer path= %s \n", path.c_str());
            auto pos = Vec2(origin.x + visibleSize.width / 2, origin.y + visibleSize.height /2);
            auto videoPlayer = VideoPlayer::create();
            videoPlayer->setPosition(pos);
            videoPlayer->setAnchorPoint(Vec2::ANCHOR_MIDDLE);
            videoPlayer->setContentSize(visibleSize);
            this->addChild(videoPlayer);
            
            videoPlayer->addEventListener([this](Ref* sender, VideoPlayer::EventType eventType)
            {
                VideoPlayer *vv = dynamic_cast<VideoPlayer*>(sender);
                switch (eventType)
                {
                case VideoPlayer::EventType::STOPPED:
                    cocos2d::log("InstallLayer VideoPlayer STOPPED\n");
                    vv->setVisible(false);
                    _blackLayer->setVisible(false);
                    break;
                case VideoPlayer::EventType::COMPLETED:
                    cocos2d::log("InstallLayer VideoPlayer COMPLETED\n");
                    vv->stop();
                    vv->setVisible(false);
                    _blackLayer->setVisible(false);
                    break;
                default:
                    break;
                }
            });
            videoPlayer->setKeepAspectRatioEnabled(true);
            videoPlayer->setFullScreenEnabled(true);
            
            videoPlayer->setFileName(path);
            videoPlayer->play();
        }
    }
#endif
    
    _updateLoadingBarVisible();
    goStart();
}
